[Android][Framework] 从一个小问题了解STK加载内容的方式


STK就是SIMToolKit。

问题如图,STK一个case的输入框,不应该能输入+:

这个界面从哪来的?
实际上,我们插入SIM卡,手机就会显示SimToolKit,打开就能看到一些和运营商相关的菜单。换了不同的卡菜单也会变。所以大概可以猜到,SIM卡里写有一些配置文件,STK会解析这些文件。

项目原因,正好可以拿到一些配置文件,如图:

通过Smartstation把配置文件写到模拟SIM卡中,然后插卡交给STK读取处理这些信息。

阅读Java文件,找到出问题的case代码:

        case 30021: 
            GetInput getinput21 = new GetInput("Enter 67#*+.digits, SMS default alphabet, Terminal to hide text, packing required, help information available,\"+\" can not input.",4,8);
            getinput21.digitsOnly();
            getinput21.noEcho();
            getinput21.textString().packed();
            getinput21.helpInformationAvailable(true);
            super.pch.sendCommand(getinput21.toByteArray());
            super.state = 0;
            break;

从文件可以知道,输入框是个GetInput对象。
输入对象配置了digitsOnlynoEchopacked等属性。

怎么处理配置文件?

有了配置文件,插SIM卡到手机,STK会处理这些数据。

在OpenGrok上搜索代码,可以找到输入部分,在STK的packages/apps/Stk/src/com/android/stk/StkInputActivity.java文件中。

下面看一下configInputDisplay方法,配置输入显示。

    private void configInputDisplay() {
        TextView numOfCharsView = (TextView) findViewById(R.id.num_of_chars);
        TextView inTypeView = (TextView) findViewById(R.id.input_type);

        int inTypeId = R.string.alphabet;

        // set the prompt.
        mPromptView.setText(mStkInput.text);

        // Set input type (alphabet/digit) info close to the InText form.
        if (mStkInput.digitOnly) {
            mTextIn.setKeyListener(StkDigitsKeyListener.getInstance());
            inTypeId = R.string.digits;
        }
        inTypeView.setText(inTypeId);

        if (mStkInput.icon != null) {
            setFeatureDrawable(Window.FEATURE_LEFT_ICON, new BitmapDrawable(
                    mStkInput.icon));
        }

        // Handle specific global and text attributes.
        switch (mState) {
        case STATE_TEXT:
            int maxLen = mStkInput.maxLen;
            int minLen = mStkInput.minLen;
            mTextIn.setFilters(new InputFilter[] {new InputFilter.LengthFilter(
                    maxLen)});

            // Set number of chars info.
            String lengthLimit = String.valueOf(minLen);
            if (maxLen != minLen) {
                lengthLimit = minLen + " - " + maxLen;
            }
            numOfCharsView.setText(lengthLimit);

            if (!mStkInput.echo) {
                mTextIn.setInputType(InputType.TYPE_CLASS_NUMBER
                                     | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
            }
            // Set default text if present.
            if (mStkInput.defaultText != null) {
                mTextIn.setText(mStkInput.defaultText);
            } else {
                // make sure the text is cleared
                mTextIn.setText("", BufferType.EDITABLE);
            }

            break;
        case STATE_YES_NO:
            // Set display mode - normal / yes-no layout
            mYesNoLayout.setVisibility(View.VISIBLE);
            mNormalLayout.setVisibility(View.GONE);
            break;
        }
    }

代码中出现mStkInput.digitOnly这样的判断,可以推断mStkInput就是和配置文件里的GetInput对象。

mStkInput来自frameworks/opt/telephony/src/java/com/android/internal/telephony/cat/Input.java

定义如下:

    Input() {
        text = "";
        defaultText = null;
        icon = null;
        minLen = 0;
        maxLen = 1;
        ucs2 = false;
        packed = false;
        digitOnly = false;
        echo = false;
        yesNo = false;
        helpAvailable = false;
        duration = null;
        iconSelfExplanatory = false;
    }

回到前面的class,因为STK file里有说明getinput21.digitsOnly();,所以会进入下面逻辑:

        // Set input type (alphabet/digit) info close to the InText form.
        if (mStkInput.digitOnly) {
            mTextIn.setKeyListener(StkDigitsKeyListener.getInstance());
            inTypeId = R.string.digits;
        }

这里mTextIn是一个EditText,setKeyListener就是过滤字符的作用。

/**
 * For entering dates in a text field.
 */
public class StkDigitsKeyListener extends NumberKeyListener {
    @Override
    protected char[] getAcceptedChars() {
        return CHARACTERS;
    }

    public int getInputType() {
        return EditorInfo.TYPE_CLASS_PHONE;
    }

    public static StkDigitsKeyListener getInstance() {
        if (sInstance != null) {
            return sInstance;
        }
        sInstance = new StkDigitsKeyListener();
        return sInstance;
    }

    /**
     * The characters that are used.
     *
     * @see KeyEvent#getMatch
     * @see #getAcceptedChars
     */
    public static final char[] CHARACTERS = new char[] {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#', '+'};

    private static StkDigitsKeyListener sInstance;
}

可以看到,CHARACTERS定义了可以输入的字符,其中包含’+’。如果不需要’+’,把这里的声明修改掉就OK

其实我也不做Tele,但通过这个过程,可以大概了解一些STK相关的原理。


文章作者: Wossoneri
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC 4.0 许可协议。转载请注明来源 Wossoneri !
评论
  目录